﻿using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace ExcelAutomator
{
	public static class ConfigurationBuilder
	{
		public static T Build<T>(string xmlConfiguration, string defaultNamespace) where T: new()
		{
			return Build<T>(XmlReader.Create(
				new StringReader(xmlConfiguration), GetXmlReaderSettings(new List<SchemaContainer>())), 
				defaultNamespace);
		}

		public static T Build<T>(string xmlConfiguration) where T: new()
		{
			return Build<T>(XmlReader.Create(new StringReader(xmlConfiguration), GetXmlReaderSettings(new List<SchemaContainer>())));
		}

		public static T Build<T>(string xmlConfiguration, IEnumerable<SchemaContainer> schemaContainers) where T: new()
		{
			return Build<T>(XmlReader.Create(new StringReader(xmlConfiguration), GetXmlReaderSettings(schemaContainers)));
		}


		public static T Build<T>(XmlReader reader, string defaultNamespace) where T: new()
		{
			var serializer = new XmlSerializer(typeof(T), defaultNamespace);
			return (T) serializer.Deserialize(reader);
		}

		public static T Build<T>(XmlReader reader) where T: new()
		{
			return Build<T>(reader, string.Empty);
		}

		public static string WriteXml(object instance, string @namespace)
		{
			var builder = new StringBuilder();
			var writer = XmlWriter.Create(builder);
			var serializer = new XmlSerializer(instance.GetType(), @namespace);
			serializer.Serialize(writer, instance);
			return builder.ToString();
		}
		
		#region GetXmlReaderSettings

		private static XmlReaderSettings GetXmlReaderSettings(IEnumerable<SchemaContainer> schemas)
		{
			var settings = new XmlReaderSettings
			{
				ConformanceLevel = ConformanceLevel.Document,
				CheckCharacters = true
			};
			
			settings.ValidationType = ValidationType.Schema;
			settings.IgnoreWhitespace = true;
			settings.IgnoreComments = true;

			foreach (var schema in schemas)
			{
				settings.Schemas.Add(schema.Namespace, XmlReader.Create(new StringReader(schema.SchemaXsd)));
			}
			settings.Schemas.Compile();

			return settings;
		}

		#endregion

	}

	#region SchemaContainer

	public class SchemaContainer
	{
		public string Namespace
		{
			get;
			private set;
		}
		public string SchemaXsd
		{
			get;
			private set;
		}

		public SchemaContainer(string ns, string schemaXsd)
		{
			Namespace = ns;
			SchemaXsd = schemaXsd;
		}
	}

	#endregion
}
